/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.anden.panningview;

import ohos.agp.animation.Animator;
import ohos.agp.components.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * AnimPanel.
 */
public class AnimPanel {
    /**
     * CENTER_PIVOT.
     */
    public static final float CENTER_PIVOT = Float.MAX_VALUE;
    private static final long DURATION = BaseViewAnimator.DURATION;
    private static final long NO_DELAY = 0;
    private BaseViewAnimator animator;
    private long duration;
    private long delay;
    private int curveType;
    private float pivotX;
    private float pivotY;
    private List<Animator.StateChangedListener> callbacks;
    private Component target;

    private AnimPanel(AnimationComposer animationComposer) {
        animator = animationComposer.animator;
        duration = animationComposer.duration;
        delay = animationComposer.delay;
        curveType = animationComposer.curveType;
        pivotX = animationComposer.pivotX;
        pivotY = animationComposer.pivotY;
        callbacks = animationComposer.callbacks;
        target = animationComposer.target;
    }

    /**
     * with
     *
     * @param enumButton Enum
     * @return anim
     */
    public static AnimationComposer with(EnumButton enumButton) {
        return new AnimationComposer(enumButton);
    }

    /**
     * with
     *
     * @param animator Enum
     * @return anim
     */
    public static AnimationComposer with(BaseViewAnimator animator) {
        return new AnimationComposer(animator);
    }

    /**
     * AnimatorCallback
     */
    public interface AnimatorCallback {
        void call(Animator animator);
    }

    private static class EmptyAnimatorListener implements Animator.StateChangedListener {
        @Override
        public void onStart(Animator animator) {
        }

        @Override
        public void onStop(Animator animator) {
        }

        @Override
        public void onCancel(Animator animator) {
        }

        @Override
        public void onEnd(Animator animator) {
        }

        @Override
        public void onPause(Animator animator) {
        }

        @Override
        public void onResume(Animator animator) {
        }
    }

    /**
     * AnimationComposer
     */
    public static final class AnimationComposer {
        private List<Animator.StateChangedListener> callbacks = new ArrayList<>();
        private BaseViewAnimator animator;
        private long duration = DURATION;
        private long delay = NO_DELAY;
        private float pivotX = AnimPanel.CENTER_PIVOT;
        private float pivotY = AnimPanel.CENTER_PIVOT;
        private int curveType;
        private Component target;

        private AnimationComposer(EnumButton enumButton) {
            this.animator = enumButton.getAnimator();
        }

        private AnimationComposer(BaseViewAnimator animator) {
            this.animator = animator;
        }

        /**
         * AnimationComposer
         *
         * @param duration long
         * @return anim
         */
        public AnimationComposer duration(long duration) {
            this.duration = duration;
            return this;
        }

        /**
         * playOn
         *
         * @param target Component
         * @return yoyo
         */
        public YoYoString playOn(Component target) {
            this.target = target;
            return new YoYoString(new AnimPanel(this).play(), this.target);
        }
    }

    /**
     * YoYo string, you can use this string to control your YoYo.
     */
    public static final class YoYoString {
        private BaseViewAnimator animator;
        private Component target;

        private YoYoString(BaseViewAnimator animator, Component target) {
            this.target = target;
            this.animator = animator;
        }

        /**
         * playOn
         *
         * @param reset true
         */
        public void stop(boolean reset) {
            animator.cancel();
            if (reset) {
                animator.reset(target);
            }
        }

        /**
         * playOn
         *
         * @param pause true
         */
        public void pause(boolean pause) {
            animator.pauseAnim();
        }

        /**
         * playOn
         *
         * @param resume true
         */
        public void resume(boolean resume) {
            animator.resumeAnim();
        }

        /**
         * clear
         *
         * @param val true
         */
        public void clear(boolean val) {
            animator.clearAnim();
        }
    }

    private BaseViewAnimator play() {
        animator.setTarget(target);
        if (pivotX == AnimPanel.CENTER_PIVOT) {
            target.setPivotX(target.getWidth() / 2.0f);
        } else {
            target.setPivotX(pivotX);
        }
        if (pivotY == AnimPanel.CENTER_PIVOT) {
            target.setPivotY(target.getHeight() / 2.0f);
        } else {
            target.setPivotY(pivotY);
        }
        animator.setDuration(duration)
                .setCurveType(curveType)
                .setStartDelay(delay);
        if (callbacks.size() > 0) {
            for (Animator.StateChangedListener callback : callbacks) {
                animator.addAnimatorListener(callback);
            }
        }

        animator.animate();
        return animator;
    }
}
